/* eslint-disable no-debugger */
const ctx: Worker = self as any
ctx.addEventListener('message', function (e) {
  console.log('ai start')
  console.log(e.data)
  try {
    chessBoard = e.data._chessBoard
    chessList = e.data.chessList
    isAIfirst = e.data.isAIfirst
  } catch (e) {
    console.error(e)
    return
  }
  // 如果是电脑先手,需要将棋子的价值倒置
  reverseChessValue(isAIfirst)
  searchResult = null
  alphaBetaSearch2(-MATE_VALUE, MATE_VALUE, MINMAXDEPTH, isAIfirst)
  ctx.postMessage(searchResult)
})

// 搜索的最大深度
const MINMAXDEPTH = 4
const MATE_VALUE = 99999
let searchResult
let chessBoard: any
let chessList: any
let isAIfirst = false
const historyTable = new Map()
// 希尔排序
const SHELL_STEP = [0, 1, 4, 13, 40, 121, 364, 1093]
const value: any = {
  // 车价值
  c: [
    [206, 208, 207, 213, 214, 213, 207, 208, 206],
    [206, 212, 209, 216, 233, 216, 209, 212, 206],
    [206, 208, 207, 214, 216, 214, 207, 208, 206],
    [206, 213, 213, 216, 216, 216, 213, 213, 206],
    [208, 211, 211, 214, 215, 214, 211, 211, 208],

    [208, 212, 212, 214, 215, 214, 212, 212, 208],
    [204, 209, 204, 212, 214, 212, 204, 209, 204],
    [198, 208, 204, 212, 212, 212, 204, 208, 198],
    [200, 208, 206, 212, 200, 212, 206, 208, 200],
    [194, 206, 204, 212, 200, 212, 204, 206, 194]
  ],

  // 马价值
  m: [
    [90, 90, 90, 96, 90, 96, 90, 90, 90],
    [90, 96, 103, 97, 94, 97, 103, 96, 90],
    [92, 98, 99, 103, 99, 103, 99, 98, 92],
    [93, 108, 100, 107, 100, 107, 100, 108, 93],
    [90, 100, 99, 103, 104, 103, 99, 100, 90],

    [90, 98, 101, 102, 103, 102, 101, 98, 90],
    [92, 94, 98, 95, 98, 95, 98, 94, 92],
    [93, 92, 94, 95, 92, 95, 94, 92, 93],
    [85, 90, 92, 93, 78, 93, 92, 90, 85],
    [88, 85, 90, 88, 90, 88, 90, 85, 88]
  ],

  // 相价值
  x: [
    [0, 0, 20, 0, 0, 0, 20, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 23, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 20, 0, 0, 0, 20, 0, 0],

    [0, 0, 20, 0, 0, 0, 20, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [18, 0, 0, 0, 23, 0, 0, 0, 18],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 20, 0, 0, 0, 20, 0, 0]
  ],

  // 士价值
  s: [
    [0, 0, 0, 20, 0, 20, 0, 0, 0],
    [0, 0, 0, 0, 23, 0, 0, 0, 0],
    [0, 0, 0, 20, 0, 20, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],

    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 20, 0, 20, 0, 0, 0],
    [0, 0, 0, 0, 23, 0, 0, 0, 0],
    [0, 0, 0, 20, 0, 20, 0, 0, 0]
  ],

  // 将价值
  j: [
    [0, 0, 0, 8888, 8888, 8888, 0, 0, 0],
    [0, 0, 0, 8888, 8888, 8888, 0, 0, 0],
    [0, 0, 0, 8888, 8888, 8888, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],

    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 8888, 8888, 8888, 0, 0, 0],
    [0, 0, 0, 8888, 8888, 8888, 0, 0, 0],
    [0, 0, 0, 8888, 8888, 8888, 0, 0, 0]
  ],

  // 炮价值
  p: [

    [100, 100, 96, 91, 90, 91, 96, 100, 100],
    [98, 98, 96, 92, 89, 92, 96, 98, 98],
    [97, 97, 96, 91, 92, 91, 96, 97, 97],
    [96, 99, 99, 98, 100, 98, 99, 99, 96],
    [96, 96, 96, 96, 100, 96, 96, 96, 96],

    [95, 96, 99, 96, 100, 96, 99, 96, 95],
    [96, 96, 96, 96, 96, 96, 96, 96, 96],
    [97, 96, 100, 99, 101, 99, 100, 96, 97],
    [96, 97, 98, 98, 98, 98, 98, 97, 96],
    [96, 96, 97, 99, 99, 99, 97, 96, 96]
  ],

  // 卒价值
  b: [
    [9, 9, 9, 11, 13, 11, 9, 9, 9],
    [19, 24, 34, 42, 44, 42, 34, 24, 19],
    [19, 24, 32, 37, 37, 37, 32, 24, 19],
    [19, 23, 27, 29, 30, 29, 27, 23, 19],
    [14, 18, 20, 27, 29, 27, 20, 18, 14],

    [7, 0, 13, 0, 16, 0, 13, 0, 7],
    [7, 0, 7, 0, 15, 0, 7, 0, 7],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0]
  ]
}

// 黑子为红字价值位置的倒置
value.C = arrClone(value.c).reverse()
value.M = arrClone(value.m).reverse()
value.X = value.x
value.S = value.s
value.J = value.j
value.P = arrClone(value.p).reverse()
value.B = arrClone(value.b).reverse()

// 将棋子的价值,规则倒置
function reverseChessValue(isAIfirst: boolean) {
  if (isAIfirst) {
    let c = value.C
    let m = value.M
    let p = value.P
    let b = value.B
    value.C = value.c
    value.M = value.m
    value.P = value.p
    value.B = value.b
    value.c = c
    value.m = m
    value.p = p
    value.b = b
  }
}

// 记录杀死的棋子，用于回退
const killChess: any[] = []
function setPostion(id: string, x: number, y: number, back: boolean) {
  // 回退
  if (back) {
    const preChess = killChess.pop()
    // 设置棋子起点信息
    chessBoard[chessList[id].x][chessList[id].y] = preChess
    if (preChess) chessList[preChess].display = 'block'
    // 设置落子信息
    chessBoard[x][y] = id
    chessList[id].x = x
    chessList[id].y = y
  } else {
    // 设置棋子起点信息
    chessBoard[chessList[id].x][chessList[id].y] = ''
    // 设置落子信息
    const chessKilled = chessBoard[x][y]
    if (chessKilled) chessList[chessKilled].display = 'none'
    killChess.push(chessKilled)
    chessBoard[x][y] = id
    chessList[id].x = x
    chessList[id].y = y
  }
}

function arrClone(arr: string | any[]) {
  const newArr = []
  for (let i = 0; i < arr.length; i++) {
    newArr[i] = arr[i].slice()
  }
  return newArr
}

// 评估棋局 取得棋盘双方棋子价值差，后手情况下正数代表黑方优势，负数代表红方优势
function evaluate() {
  let val = 0
  if (isAIfirst) {
    Object.keys(chessList).forEach(key => {
      if (chessList[key].display == 'block') {
        const chessType = key.slice(0, 1)
        if (chessType == chessType.toLocaleLowerCase()) {
          val += value[chessType][chessList[key].x][chessList[key].y]
        } else {
          val -= value[chessType][chessList[key].x][chessList[key].y]
        }
      }
    })
  } else {
    Object.keys(chessList).forEach(key => {
      if (chessList[key].display == 'block') {
        const chessType = key.slice(0, 1)
        if (chessType == chessType.toLocaleLowerCase()) {
          val -= value[chessType][chessList[key].x][chessList[key].y]
        } else {
          val += value[chessType][chessList[key].x][chessList[key].y]
        }
      }
    })
  }
  return val
}

function shellSort(mvs: any[], vls: any[]) {
  let stepLevel = 1
  while (SHELL_STEP[stepLevel] < mvs.length) {
    stepLevel++
  }
  stepLevel--
  while (stepLevel > 0) {
    const step = SHELL_STEP[stepLevel]
    for (let i = step; i < mvs.length; i++) {
      const mvBest = mvs[i]
      const vlBest = vls[i]
      let j = i - step
      while (j >= 0 && vlBest > vls[j]) {
        mvs[j + step] = mvs[j]
        vls[j + step] = vls[j]
        j -= step
      }
      mvs[j + step] = mvBest
      vls[j + step] = vlBest
    }
    stepLevel--
  }
}

function isSameGroup(id: string, chessBoardID: string) {
  return (!chessBoardID.match(/[A-Z]/)) == (!id.match(/[A-Z]/))
}

function getAllMovePosition(isRedCamp: boolean, chessList: any, chooseID: string) {

  if (isAIfirst) isRedCamp = !isRedCamp

  const getMovesFnMap: any = {
    b: function (id: any, x: number, y: number) {
      const res = []
      let findChessID = ''
      if (isRedCamp && x > 0) {
        // 红棋向上检索
        findChessID = chessBoard[x - 1][y]
        if (!findChessID || !isSameGroup(id, findChessID)) {
          res.push([x - 1, y])
        }
      } else if (x < 9) {
        // 黑棋向下检索
        findChessID = chessBoard[x + 1][y]
        if (!findChessID || !isSameGroup(id, findChessID)) {
          res.push([x + 1, y])
        }
      }
      // 兵过河左右查找
      if ((x < 5 && isRedCamp) || (x > 4 && !isRedCamp)) {
        if (y > 0) findChessID = chessBoard[x][y - 1]
        if (!findChessID || !isSameGroup(id, findChessID)) {
          res.push([x, y - 1])
        }
        if (y < 8) findChessID = chessBoard[x][y + 1]
        if (!findChessID || !isSameGroup(id, findChessID)) {
          res.push([x, y + 1])
        }
      }
      return res
    },

    s: function (id: any, x: number, y: number) {
      const res = []
      let findChessID = ''
      // 4点半
      if ((y + 1 <= 5 && x < 9 && isRedCamp) || (x + 1 <= 2 && y + 1 <= 5 && !isRedCamp)) {
        findChessID = chessBoard[x + 1][y + 1]
        if (!findChessID || !isSameGroup(id, findChessID)) res.push([x + 1, y + 1])
      }
      // 7点半
      if ((y - 1 >= 3 && x < 9 && isRedCamp) || (x + 1 <= 2 && y - 1 >= 3 && !isRedCamp)) {
        findChessID = chessBoard[x + 1][y - 1]
        if (!findChessID || !isSameGroup(id, findChessID)) res.push([x + 1, y - 1])
      }
      // 1点半
      if ((x - 1 >= 7 && y + 1 <= 5 && isRedCamp) || (y + 1 <= 5 && x > 0 && !isRedCamp)) {
        findChessID = chessBoard[x - 1][y + 1]
        if (!findChessID || !isSameGroup(id, findChessID)) res.push([x - 1, y + 1])
      }
      // 10点半
      if ((x - 1 >= 7 && y - 1 >= 3 && isRedCamp) || (y - 1 >= 3 && x > 0 && !isRedCamp)) {
        findChessID = chessBoard[x - 1][y - 1]
        if (!findChessID || !isSameGroup(id, findChessID)) res.push([x - 1, y - 1])
      }
      return res
    },

    x: function (id: any, x: number, y: number) {
      const res = []
      let findChessID = ''
      // 4点半
      if (x + 2 < 10 && y + 2 < 9 && !chessBoard[x + 1][y + 1]) {
        if (isRedCamp || (x + 2 <= 4 && !isRedCamp)) {
          findChessID = chessBoard[x + 2][y + 2]
          if (!findChessID || !isSameGroup(id, findChessID)) res.push([x + 2, y + 2])
        }
      }
      // 7点半
      if (x + 2 < 10 && y - 2 >= 0 && !chessBoard[x + 1][y - 1]) {
        if (isRedCamp || (x + 2 <= 4 && !isRedCamp)) {
          findChessID = chessBoard[x + 2][y - 2]
          if (!findChessID || !isSameGroup(id, findChessID)) res.push([x + 2, y - 2])
        }
      }
      // 1点半
      if (x - 2 >= 0 && y + 2 < 9 && !chessBoard[x - 1][y + 1]) {
        if ((x - 2 >= 5 && isRedCamp) || !isRedCamp) {
          findChessID = chessBoard[x - 2][y + 2]
          if (!findChessID || !isSameGroup(id, findChessID)) res.push([x - 2, y + 2])
        }
      }
      // 10点半
      if (x - 2 >= 0 && y - 2 >= 0 && !chessBoard[x - 1][y - 1]) {
        if ((x - 2 >= 5 && isRedCamp) || !isRedCamp) {
          findChessID = chessBoard[x - 1][y - 1]
          if (!findChessID || !isSameGroup(id, findChessID)) res.push([x - 2, y - 2])
        }
      }
      return res
    },

    j: function (id: any, x: number, y: number) {
      const res = []
      let findChessID = ''
      const isNull = (() => {
        let x1 = chessList.j1.x
        let x2 = chessList.J1.x
        if (x1 < x2) {
          [x1, x2] = [x2, x1]
        }
        for (let i = x1 - 1; i > x2; i--) {
          if (chessBoard[i][y]) return false
        }
        return true
      })()
      // 下
      if ((x + 1 < 10 && isRedCamp) || (x + 1 <= 2 && !isRedCamp)) {
        findChessID = chessBoard[x + 1][y]
        if (!findChessID || !isSameGroup(id, findChessID)) res.push([x + 1, y])
      }

      // 上
      if ((x - 1 >= 7 && isRedCamp) || (x - 1 >= 0 && !isRedCamp)) {
        findChessID = chessBoard[x - 1][y]
        if (!findChessID || !isSameGroup(id, findChessID)) res.push([x - 1, y])
      }
      // 老将对老将的情况
      if (chessList.J1.y == chessList.j1.y && isNull) {
        res.push([chessList.J1.x, y])
      }
      // 右
      if (y + 1 <= 5) {
        findChessID = chessBoard[x][y + 1]
        if (!findChessID || !isSameGroup(id, findChessID)) res.push([x, y + 1])
      }
      // 左
      if (y - 1 >= 3) {
        findChessID = chessBoard[x][y - 1]
        if (!findChessID || !isSameGroup(id, findChessID)) res.push([x, y - 1])
      }

      return res
    },

    p: function (id: any, x: number, y: number) {
      const res = []
      // 上检索
      let n = 0
      for (let i = x - 1; i >= 0; i--) {
        if (chessBoard[i][y]) {
          if (n == 0) {
            n++
            continue
          } else {
            if (!isSameGroup(id, chessBoard[i][y])) res.push([i, y])
            break
          }
        } else {
          if (n == 0) res.push([i, y])
        }
      }
      // 下检索
      n = 0
      for (let i = x + 1; i <= 9; i++) {
        if (chessBoard[i][y]) {
          if (n == 0) {
            n++
            continue
          } else {
            if (!isSameGroup(id, chessBoard[i][y])) res.push([i, y])
            break
          }
        } else {
          if (n == 0) res.push([i, y])
        }
      }
      // 左检索
      n = 0
      for (let i = y - 1; i >= 0; i--) {
        if (chessBoard[x][i]) {
          if (n == 0) {
            n++
            continue
          } else {
            if (!isSameGroup(id, chessBoard[x][i])) res.push([x, i])
            break
          }
        } else {
          if (n == 0) res.push([x, i])
        }
      }
      // 右检索
      n = 0
      for (let i = y + 1; i <= 8; i++) {
        if (chessBoard[x][i]) {
          if (n == 0) {
            n++
            continue
          } else {
            if (!isSameGroup(id, chessBoard[x][i])) res.push([x, i])
            break
          }
        } else {
          if (n == 0) res.push([x, i])
        }
      }
      return res
    },

    m: function (id: any, x: number, y: number) {
      const res = []
      // 1点
      if (x - 2 >= 0 && y + 1 <= 8 && !chessBoard[x - 1][y] && (!chessBoard[x - 2][y + 1] || !isSameGroup(id, chessBoard[x - 2][y + 1]))) res.push([x - 2, y + 1])
      // 2点
      if (x - 1 >= 0 && y + 2 <= 8 && !chessBoard[x][y + 1] && (!chessBoard[x - 1][y + 2] || !isSameGroup(id, chessBoard[x - 1][y + 2]))) res.push([x - 1, y + 2])
      // 4点
      if (x + 1 <= 9 && y + 2 <= 8 && !chessBoard[x][y + 1] && (!chessBoard[x + 1][y + 2] || !isSameGroup(id, chessBoard[x + 1][y + 2]))) res.push([x + 1, y + 2])
      // 5点
      if (x + 2 <= 9 && y + 1 <= 8 && !chessBoard[x + 1][y] && (!chessBoard[x + 2][y + 1] || !isSameGroup(id, chessBoard[x + 2][y + 1]))) res.push([x + 2, y + 1])
      // 7点
      if (x + 2 <= 9 && y - 1 >= 0 && !chessBoard[x + 1][y] && (!chessBoard[x + 2][y - 1] || !isSameGroup(id, chessBoard[x + 2][y - 1]))) res.push([x + 2, y - 1])
      // 8点
      if (x + 1 <= 9 && y - 2 >= 0 && !chessBoard[x][y - 1] && (!chessBoard[x + 1][y - 2] || !isSameGroup(id, chessBoard[x + 1][y - 2]))) res.push([x + 1, y - 2])
      // 10点
      if (x - 1 >= 0 && y - 2 >= 0 && !chessBoard[x][y - 1] && (!chessBoard[x - 1][y - 2] || !isSameGroup(id, chessBoard[x - 1][y - 2]))) res.push([x - 1, y - 2])
      // 11点
      if (x - 2 >= 0 && y - 1 >= 0 && !chessBoard[x - 1][y] && (!chessBoard[x - 2][y - 1] || !isSameGroup(id, chessBoard[x - 2][y - 1]))) res.push([x - 2, y - 1])

      return res
    },

    c: function (id: any, x: number, y: number) {
      const res = []
      // 上检索
      for (let i = x - 1; i >= 0; i--) {
        if (!chessBoard[i][y]) {
          res.push([i, y])
          continue
        } else if (!isSameGroup(id, chessBoard[i][y])) {
          res.push([i, y])
        }
        break
      }
      // 下检索
      for (let i = x + 1; i <= 9; i++) {
        if (!chessBoard[i][y]) {
          res.push([i, y])
          continue
        } else if (!isSameGroup(id, chessBoard[i][y])) {
          res.push([i, y])
        }
        break
      }
      // 左检索
      for (let i = y - 1; i >= 0; i--) {
        if (!chessBoard[x][i]) {
          res.push([x, i])
          continue
        } else if (!isSameGroup(id, chessBoard[x][i])) {
          res.push([x, i])
        }
        break
      }
      // 右检索
      for (let i = y + 1; i <= 8; i++) {
        if (!chessBoard[x][i]) {
          res.push([x, i])
          continue
        } else if (!isSameGroup(id, chessBoard[x][i])) {
          res.push([x, i])
        }
        break
      }
      return res
    }
  }
  return getMovesFnMap[chooseID.slice(0, 1).toLocaleLowerCase()](chooseID, chessList[chooseID].x, chessList[chooseID].y)
}

function getMoves(isRedCamp: any) {
  const moves = []
  // let foul = play.isFoul;
  const keys = Object.keys(chessList)
  for (let i = 0; i < keys.length; i++) {
    const attr = chessList[keys[i]]
    if (attr.isRed != isRedCamp) {
      // 跳过红棋
      i += 15
      continue
    }
    // 跳过阵亡的棋子
    if (attr.display != 'block') continue
    const val = getAllMovePosition(isRedCamp, chessList, keys[i])
    for (let n = 0; n < val.length; n++) {
      const x = attr.x
      const y = attr.y
      const newX = val[n][0]
      const newY = val[n][1]
      // 如果不是长将着法
      // if (foul[0] != x || foul[1] != y || foul[2] != newX || foul[3] != newY) {
      // 	moves.push([x, y, newX, newY, man.key])
      // }
      moves.push([x, y, newX, newY, keys[i]])
    }
  }
  return moves
}

class MoveSort {
  mvs: any[]
  vls: any[]
  index: number
  constructor(isRedCamp: boolean) {
    this.mvs = [] // 走法数组，存储当前局面所有走法
    this.vls = [] // 在历史表中，每个走法对应的分值
    this.index = 0
    // 生成全部走法
    const mvsAll = getMoves(isRedCamp)

    for (let i = 0; i < mvsAll.length; i++) {
      const move = mvsAll[i]
      this.mvs.push(move)
      this.vls.push(getBestMove(move)) // 获取历史表中，该走法的值
    }
    shellSort(this.mvs, this.vls) // 根据历史表的分值，对走法进行排序
  }

  // 获得一步排序后的走法。如果走法已经全部获取，则返回0
  next() {
    while (this.index < this.mvs.length) {
      const mv = this.mvs[this.index]
      this.index++
      return mv
    }
    return 0
  }
}

// 更新历史表
function setBestMove(move: number, depth: number) {
  const mv = JSON.stringify(move)
  if (historyTable.has(mv)) {
    const value = historyTable.get(mv) + depth * depth
    historyTable.set(mv, value)
  } else {
    historyTable.set(mv, depth * depth)
  }
}

// 获取历史表某一走法的值
function getBestMove(move: any[]) {
  const mv = JSON.stringify(move)
  if (historyTable.has(mv)) {
    return historyTable.get(mv)
  }
  return 0
}

function checkedIsDead(camp: boolean) {
  let ID, j, m, c, p
  if (camp) {
    ID = 'j1'
    j = 'J'
    m = 'M'
    c = 'C'
    p = 'P'
  } else {
    ID = 'J1'
    j = 'j'
    m = 'm'
    c = 'c'
    p = 'p'
  }

  const pos = { x: chessList[ID].x, y: chessList[ID].y }
  let a = ''
  if (isAIfirst) {
    // 判断对方兵是否攻击到己方老将
    if (camp == true) {
      if ((pos.x + 1 <= 9 && chessBoard[pos.x + 1][pos.y].includes('B')) ||
        (pos.y + 1 <= 8 && chessBoard[pos.x][pos.y + 1].includes('B')) ||
        (pos.y - 1 >= 0 && chessBoard[pos.x][pos.y - 1].includes('B'))) {
        return true
      }
    } else {
      if ((pos.x - 1 >= 0 && chessBoard[pos.x - 1][pos.y].includes('b')) ||
        (pos.y + 1 <= 8 && chessBoard[pos.x][pos.y + 1].includes('b')) ||
        (pos.y - 1 >= 0 && chessBoard[pos.x][pos.y - 1].includes('b'))) {
        return true
      }
    }
  } else {
    // 判断对方兵是否攻击到己方老将
    if (camp == true) {
      if ((pos.x - 1 >= 0 && chessBoard[pos.x - 1][pos.y].includes('B')) ||
        (pos.y + 1 <= 8 && chessBoard[pos.x][pos.y + 1].includes('B')) ||
        (pos.y - 1 >= 0 && chessBoard[pos.x][pos.y - 1].includes('B'))) {
        return true
      }
    } else {
      if ((pos.x + 1 <= 9 && chessBoard[pos.x + 1][pos.y].includes('b')) ||
        (pos.y + 1 <= 8 && chessBoard[pos.x][pos.y + 1].includes('b')) ||
        (pos.y - 1 >= 0 && chessBoard[pos.x][pos.y - 1].includes('b'))) {
        return true
      }
    }
  }


  // 判断对方马是否攻击到己方老将
  for (let i = -1; i <= 1; i += 2) {
    for (let z = -1; z <= 1; z += 2) {
      if (pos.x + i + i <= 9 && pos.x + i + i >= 0 && pos.y + z >= 0 && pos.y + z <= 8) {
        if (!chessBoard[pos.x + i][pos.y + z]) {
          if (chessBoard[pos.x + i + i][pos.y + z].includes(m)) {
            // console.warn(m,chessBoard[pos.x + i + i][pos.y + z], pos.x + i + i, pos.y + z, pos)
            return true
          }
        }
      }
      if (pos.x + i <= 9 && pos.x + i >= 0 && pos.y + z + z >= 0 && pos.y + z + z <= 8) {
        if (!chessBoard[pos.x + i][pos.y + z]) {
          if (chessBoard[pos.x + i][pos.y + z + z].includes(m)) {
            // console.warn(m,chessBoard[pos.x + i][pos.y + z + z], pos.x + i, pos.y + z + z, pos)
            return true
          }
        }
      }
    }
  }

  // 判断对方的车、炮是攻击到了己方老将，以及将帅是否对脸

  // 上检索
  let n = 0
  for (let i = pos.x - 1; i >= 0; i--) {
    if (chessBoard[i][pos.y]) {
      if (n == 0) {
        if (chessBoard[i][pos.y].includes(c) || chessBoard[i][pos.y].includes(j)) {
          return true
        }
        n++
        continue
      } else {
        if (chessBoard[i][pos.y].includes(p)) {
          return true
        }
        break
      }
    }
  }
  // 下检索
  n = 0
  for (let i = pos.x + 1; i <= 9; i++) {
    if (chessBoard[i][pos.y]) {
      if (n == 0) {
        if (chessBoard[i][pos.y].includes(c) || chessBoard[i][pos.y].includes(j)) {
          return true
        }
        n++
      } else {
        if (n == 1 && chessBoard[i][pos.y].includes(p)) {
          return true
        }
        break
      }
    }
  }
  // 左检索
  n = 0
  for (let i = pos.y - 1; i >= 0; i--) {
    if (chessBoard[pos.x][i]) {
      if (n == 0) {
        if (chessBoard[pos.x][i].includes(c)) {
          return true
        }
        n++
        continue
      } else {
        if (chessBoard[pos.x][i].includes(p)) {
          return true
        }
        break
      }
    }
  }
  // 右检索
  n = 0
  for (let i = pos.y + 1; i <= 8; i++) {
    if (chessBoard[pos.x][i]) {
      if (n == 0) {
        if (chessBoard[pos.x][i].includes(c)) {
          return true
        }
        n++
        continue
      } else {
        if (chessBoard[pos.x][i].includes(p)) {
          return true
        }
        break
      }
    }
  }
  return false
}

function alphaBetaSearch2(vlAlpha_: number, vlBeta: number, depth: number, isMy: boolean) {
  let vlAlpha = vlAlpha_ // 初始最优值，不再是负无穷

  // 搜索分为以下几个阶段

  // 1. 到达水平线或将军，则返回局面评价值
  if (depth == 0) {
    return evaluate()
  }

  // 2. 初始化最佳走法
  let mvBest = 0 // 这样可以知道，是否搜索到了Beta截断或PV走法，以便保存到历史表

  // 3. 生成全部走法，并根据历史表排序
  const sort = new MoveSort(isMy)

  // 4. 逐一走这些走法，并进行递归
  let mv
  let vl = 0
  let isDead = false

  // 注：Alpha为下界，Beta为上界
  if ((MINMAXDEPTH & 1) == (depth & 1)) { // 取极大值，进行Beta剪枝(电脑回合)
    while ((mv = sort.next())) {
      const key = mv[4]
      const oldX = mv[0]
      const oldY = mv[1]
      const newX = mv[2]
      const newY = mv[3]
      const clearKey = chessBoard[newX][newY]

      setPostion(key, newX, newY, false)

      // 己方能将军
      if ((clearKey == 'j1' && !isAIfirst) || (clearKey == 'J1' && isAIfirst)) {
        searchResult = {
          key: key,
          x: newX,
          y: newY,
          value: MATE_VALUE
        }
        return MATE_VALUE
      } else {
        isDead = checkedIsDead(isMy)
        // 这招棋走完后，己方老将处于被攻击的状态，这是在送死。应该跳过这招棋，继续后面的搜索。
        if (isDead) {
          // 撤消这个走法;
          setPostion(key, oldX, oldY, true)
          continue
        }
        vl = alphaBetaSearch2(vlAlpha, vlBeta, depth - 1, !isMy) // 递归调用
      }

      // 撤消这个走法;
      setPostion(key, oldX, oldY, true)

      // 5. 进行Alpha-Beta大小判断和截断
      if (vl > vlAlpha) { // 找到最佳值
        // 更新Alpha值
        vlAlpha = vl
        // 如果回到了根节点，需要记录根节点的最佳走法
        if (depth == MINMAXDEPTH) {
          searchResult = {
            key: key,
            x: newX,
            y: newY,
            value: vlAlpha
          }
        }
        if (vlAlpha >= vlBeta) {
          mvBest = mv // 发生剪枝的走法要保存到历史表
          return vlBeta // Beta剪枝
        }
      }
    }
    // 找到了好的走法，更新历史表
    if (mvBest != 0) {
      setBestMove(mvBest, depth)
    }
    return vlAlpha
  } else { // 取极小值，进行Alpha剪枝(玩家回合)
    while ((mv = sort.next())) {
      const key = mv[4]
      const oldX = mv[0]
      const oldY = mv[1]
      const newX = mv[2]
      const newY = mv[3]
      const clearKey = chessBoard[newX][newY]

      setPostion(key, newX, newY, false)

      // 己方能将军
      if ((clearKey == 'j1' && isAIfirst) || (clearKey == 'J1' && !isAIfirst)) {
        searchResult = {
          key: key,
          x: newX,
          y: newY,
          value: MATE_VALUE
        }
        return MATE_VALUE
      } else {
        // 这招棋走完后，己方老将处于被攻击的状态，这是在送死。应该跳过这招棋，继续后面的搜索。
        if (checkedIsDead(isMy)) {
          // 撤消这个走法;
          // console.warn(`老将处于被攻击的状态，注意了`, isMy, mv, depth);
          setPostion(key, oldX, oldY, true)
          continue
        }
        vl = alphaBetaSearch2(vlAlpha, vlBeta, depth - 1, !isMy) // 递归调用
      }

      // 撤消这个走法;
      setPostion(key, oldX, oldY, true)

      // 5. 进行Alpha-Beta大小判断和截断
      if (vl < vlBeta) { // 找到最佳值
        // 更新Beta值
        vlBeta = vl
        if (vlAlpha >= vlBeta) {
          mvBest = mv // 发生剪枝的走法要保存到历史表
          return vlAlpha // Alpha剪枝
        }
      }
    }
    // 找到了好的走法，更新历史表
    if (mvBest != 0) {
      setBestMove(mvBest, depth)
    }
    return vlBeta
  }
}
